﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Reflection
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design
Imports System.Workflow.Runtime

Namespace System.Workflow.Activities
    <SRDescription("WebServiceResponseActivityDescription"), ActivityValidator(GetType(WebServiceResponseValidator)), SRCategory("Standard"), DefaultEvent("SendingOutput"), ToolboxBitmap(GetType(WebServiceOutputActivity), "Resources.WebServiceOut.png"), Designer(GetType(WebServiceResponseDesigner), GetType(IDesigner))> _
    Public NotInheritable Class WebServiceOutputActivity
        Inherits Activity
        Implements IPropertyValueProvider, IDynamicPropertyTypeProvider
        ' Events
        <SRDescription("OnBeforeResponseDescr"), SRCategory("Handlers"), MergableProperty(False)> _
        Public Custom Event SendingOutput As EventHandler
            AddHandler(ByVal value As EventHandler)
                MyBase.AddHandler(WebServiceOutputActivity.SendingOutputEvent, value)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler)
                MyBase.RemoveHandler(WebServiceOutputActivity.SendingOutputEvent, value)
            End RemoveHandler
        End Event

        ' Methods
        Public Sub New()
            MyBase.SetReadOnlyPropertyValue(WebServiceOutputActivity.ParameterBindingsProperty, New WorkflowParameterBindingCollection(Me))
        End Sub

        Public Sub New(ByVal name As String)
            MyBase.New(name)
            MyBase.SetReadOnlyPropertyValue(WebServiceOutputActivity.ParameterBindingsProperty, New WorkflowParameterBindingCollection(Me))
        End Sub

        Protected Overrides Function Execute(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            Dim service As WorkflowQueuingService = executionContext.GetService([Of] WorkflowQueuingService)
            MyBase.RaiseEvent(WebServiceOutputActivity.SendingOutputEvent, Me, EventArgs.Empty)
            Dim activityByName As WebServiceInputActivity = [TryCast](MyBase.GetActivityByName(Me.InputActivityName),WebServiceInputActivity)
            If (activityByName Is Nothing) Then
                Dim activity2 As Activity = MyBase.Parent
                Do While (Not activity2 Is Nothing)
                    Dim activityQualifiedName As String = (activity2.QualifiedName & "." & Me.InputActivityName)
                    activityByName = [TryCast](MyBase.GetActivityByName(activityQualifiedName),WebServiceInputActivity)
                    If (Not activityByName Is Nothing) Then
                        Exit Do
                    End If
                    activity2 = MyBase.Parent
                Loop
            End If
            If (activityByName Is Nothing) Then
                Throw New InvalidOperationException(SR.GetString("Error_CannotResolveWebServiceInput", New Object() { MyBase.QualifiedName, Me.InputActivityName }))
            End If
            Dim queueName As IComparable = New EventQueueName(activityByName.InterfaceType, activityByName.MethodName, activityByName.QualifiedName)
            Dim method As MethodInfo = activityByName.InterfaceType.GetMethod(activityByName.MethodName)
            If Not service.Exists(queueName) Then
                If (method.ReturnType Is GetType(Void)) Then
                    Return ActivityExecutionStatus.Closed
                End If
                Dim flag As Boolean = False
                Dim info2 As ParameterInfo
                For Each info2 In method.GetParameters
                    If (info2.ParameterType.IsByRef OrElse (info2.IsIn AndAlso info2.IsOut)) Then
                        flag = True
                    End If
                Next
                If flag Then
                    Return ActivityExecutionStatus.Closed
                End If
            End If
            If Not service.Exists(queueName) Then
                Throw New InvalidOperationException(SR.GetString("Error_WebServiceInputNotProcessed", New Object() { activityByName.QualifiedName }))
            End If
            Dim message As IMethodResponseMessage = Nothing
            Dim workflowQueue As WorkflowQueue = service.GetWorkflowQueue(queueName)
            If (workflowQueue.Count <> 0) Then
                message = [TryCast](workflowQueue.Dequeue,IMethodResponseMessage)
            End If
            Dim parameterBindings As WorkflowParameterBindingCollection = Me.ParameterBindings
            Dim outArgs As New ArrayList
            If Me.ParameterBindings.Contains("(ReturnValue)") Then
                Dim binding As WorkflowParameterBinding = Me.ParameterBindings.Item("(ReturnValue)")
                If (Not binding Is Nothing) Then
                    outArgs.Add(binding.Value)
                End If
            End If
            Dim info3 As ParameterInfo
            For Each info3 In method.GetParameters
                If (info3.ParameterType.IsByRef OrElse (info3.IsIn AndAlso info3.IsOut)) Then
                    Dim binding2 As WorkflowParameterBinding = parameterBindings.Item(info3.Name)
                    outArgs.Add(binding2.Value)
                End If
            Next
            message.SendResponse(outArgs)
            Return ActivityExecutionStatus.Closed
        End Function

        Friend Sub GetParameterPropertyDescriptors(ByVal properties As IDictionary)
            If (Not Me.Site Is Nothing) Then
                Dim service As ITypeProvider = DirectCast(Me.Site.GetService(GetType(ITypeProvider)), ITypeProvider)
                If (service Is Nothing) Then
                    Throw New InvalidOperationException(SR.GetString("General_MissingService", New Object() { GetType(ITypeProvider).FullName }))
                End If
                If ((Not Me.InputActivityName Is Nothing) AndAlso Not String.IsNullOrEmpty(Me.InputActivityName.Trim)) Then
                    Dim activity As WebServiceInputActivity = [TryCast](Helpers.ParseActivity(Helpers.GetRootActivity(Me), Me.InputActivityName),WebServiceInputActivity)
                    If (Not activity Is Nothing) Then
                        Dim interfaceType As Type = Nothing
                        If (Not activity.InterfaceType Is Nothing) Then
                            interfaceType = service.GetType(activity.InterfaceType.AssemblyQualifiedName)
                        End If
                        If (Not interfaceType Is Nothing) Then
                            Dim interfaceMethod As MethodInfo = Helpers.GetInterfaceMethod(interfaceType, activity.MethodName)
                            If ((Not interfaceMethod Is Nothing) AndAlso (WebServiceActivityHelpers.ValidateParameterTypes(interfaceMethod).Count = 0)) Then
                                Dim list As List([Of] ParameterInfo)
                                Dim list2 As List([Of] ParameterInfo)
                                WebServiceActivityHelpers.GetParameterInfo(interfaceMethod, list, list2)
                                Dim info2 As ParameterInfo
                                For Each info2 In list2
                                    Dim descriptor As PropertyDescriptor = Nothing
                                    If (info2.Position = -1) Then
                                        descriptor = New ParameterInfoBasedPropertyDescriptor(GetType(WebServiceOutputActivity), info2, False, New Attribute() { DesignOnlyAttribute.Yes })
                                    Else
                                        descriptor = New ParameterInfoBasedPropertyDescriptor(GetType(WebServiceOutputActivity), info2, True, New Attribute() { DesignOnlyAttribute.Yes })
                                    End If
                                    If (Not descriptor Is Nothing) Then
                                        properties.Item(descriptor.Name) = descriptor
                                    End If
                                Next
                            End If
                        End If
                    End If
                End If
            End If
        End Sub

        Protected Overrides Sub Initialize(ByVal provider As IServiceProvider)
            If (MyBase.Parent Is Nothing) Then
                Throw New InvalidOperationException(SR.GetString("Error_MustHaveParent"))
            End If
            MyBase.Initialize(provider)
        End Sub

        Private Function System.Workflow.ComponentModel.Design.IPropertyValueProvider.GetPropertyValues(ByVal context As ITypeDescriptorContext) As ICollection Implements IPropertyValueProvider.GetPropertyValues
            Dim strings As New StringCollection
            If (context.PropertyDescriptor.Name = "InputActivityName") Then
                Dim activity As Activity
                For Each activity In WebServiceActivityHelpers.GetPreceedingActivities(Me)
                    If TypeOf activity Is WebServiceInputActivity Then
                        strings.Add(activity.QualifiedName)
                    End If
                Next
            End If
            Return strings
        End Function

        Private Function System.Workflow.ComponentModel.IDynamicPropertyTypeProvider.GetAccessType(ByVal serviceProvider As IServiceProvider, ByVal propertyName As String) As AccessTypes Implements IDynamicPropertyTypeProvider.GetAccessType
            If (propertyName Is Nothing) Then
                Throw New ArgumentNullException("propertyName")
            End If
            Return AccessTypes.Read
        End Function

        Private Function System.Workflow.ComponentModel.IDynamicPropertyTypeProvider.GetPropertyType(ByVal serviceProvider As IServiceProvider, ByVal propertyName As String) As Type Implements IDynamicPropertyTypeProvider.GetPropertyType
            If (propertyName Is Nothing) Then
                Throw New ArgumentNullException("propertyName")
            End If
            Dim properties As New Dictionary([Of] String, Object)
            Me.GetParameterPropertyDescriptors(properties)
            If properties.ContainsKey(propertyName) Then
                Dim descriptor As ParameterInfoBasedPropertyDescriptor = [TryCast](properties.Item(propertyName),ParameterInfoBasedPropertyDescriptor)
                If (Not descriptor Is Nothing) Then
                    Return descriptor.ParameterType
                End If
            End If
            Return Nothing
        End Function


        ' Properties
        <RefreshProperties(RefreshProperties.All), SRCategory("Activity"), DefaultValue(""), SRDescription("ReceiveActivityNameDescription"), TypeConverter(GetType(PropertyValueProviderTypeConverter)), MergableProperty(False)> _
        Public Property InputActivityName As String
            Get
                Return [TryCast](MyBase.GetValue(WebServiceOutputActivity.InputActivityNameProperty),String)
            End Get
            Set(ByVal value As String)
                MyBase.SetValue(WebServiceOutputActivity.InputActivityNameProperty, value)
            End Set
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property ParameterBindings As WorkflowParameterBindingCollection
            Get
                Return [TryCast](MyBase.GetValue(WebServiceOutputActivity.ParameterBindingsProperty),WorkflowParameterBindingCollection)
            End Get
        End Property


        ' Fields
        Public Shared ReadOnly InputActivityNameProperty As DependencyProperty = DependencyProperty.Register("InputActivityName", GetType(String), GetType(WebServiceOutputActivity), New PropertyMetadata("", DependencyPropertyOptions.Metadata))
        Public Shared ReadOnly ParameterBindingsProperty As DependencyProperty = DependencyProperty.Register("ParameterBindings", GetType(WorkflowParameterBindingCollection), GetType(WebServiceOutputActivity), New PropertyMetadata((DependencyPropertyOptions.Metadata Or DependencyPropertyOptions.ReadOnly), New Attribute() { New BrowsableAttribute(False), New DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) }))
        Public Shared ReadOnly SendingOutputEvent As DependencyProperty = DependencyProperty.Register("SendingOutput", GetType(EventHandler), GetType(WebServiceOutputActivity))
    End Class
End Namespace

